package com.barks.learning.base.controller;

import cn.hutool.core.util.RandomUtil;
import com.barks.learning.base.async.DeferredResultHolder;
import com.barks.learning.base.async.TaskQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.concurrent.Callable;

/**
 * @author chenw-i
 * @version 1.0.0
 * @ClassName AsyncDemo.java
 * @Description spring mvc 异步请求demo
 * @createTime 2020年07月11日 18:33:00
 */
@RestController
public class AsyncDemo {
    private Logger logger = LoggerFactory.getLogger(AsyncDemo.class);

    @Autowired
    TaskQueue taskQueue;

    @Autowired
    DeferredResultHolder holder;

    /**
     * 使用Callable的方式实现异步
     * 场景：
     *     处理常规的耗时操作
     * @return
     */
    @GetMapping("/callable")
    public Callable<String> callable(){
        logger.info("callable before");
        Callable<String> callable = new Callable<String>() {
            public String call() throws Exception {
                logger.info("callable 异步处理中");
                // 模拟网络延时
                Thread.sleep(1000);
                return "callable success";
            }
        };
        logger.info("callable after");
        return callable;
    }

    /**
     * DeferredResult
     * 场景：
     *      异步任务需要使用三方消息队列，等待处理完成之后这里再给出响应
     * @return
     */
    @GetMapping("/deferred")
    public DeferredResult<String> deferredResult(){

        logger.info("deferredResult before");
        DeferredResult<String> deferredResult = new DeferredResult<String>();

        String radomStr = RandomUtil.randomStringUpper(10);
        /*
        模拟将需要做异步的任务放入队列，让三方服务去完成任务，待结果放入队列中
         */
        taskQueue.pushTask(radomStr);
        /*
        同时当前请求挂起，等待任务完成后  通过ApplicationListener 触发完成响应
        具体可以看  #DeferredResultListener
         */
        holder.putDeferredResult(radomStr,deferredResult);
        logger.info("deferredResult after");
        return deferredResult;
    }
}
